package com.fsh.lingsp.common.common.thread;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 作者：fsh
 * 日期：2024/02/26
 * <p>
 * 描述：线程池配置
 *       实现AsyncConfigurer接口，用于自定义异步执行配置。
 */
@Configuration// 使用@Configuration注解标记这是一个配置类，用于定义Spring的Bean。
@EnableAsync// 使用@EnableAsync注解启用异步执行支持。
public class ThreadPoolConfig implements AsyncConfigurer {

    /**
     * 重写AsyncConfigurer接口中的getAsyncExecutor方法，返回自定义的线程池
     */
    @Override
    public Executor getAsyncExecutor() {
        // 返回mallchatExecutor()方法创建的线程池。
        return lingchatExecutor();
    }


    // 定义一个常量字符串，代表项目共用的线程池的名称。
    public static final String LINGSPHERE_EXECUTOR = "lingsphereExecutor";
    /**
     * 使用@Bean注解定义一个Bean，名称为LINGSPHERE_EXECUTOR。
     * @Primary注解表示当有多个同类型的Bean时，优先选择这个Bean作为注入目标。
     */
    @Bean(LINGSPHERE_EXECUTOR)
    @Primary
    public ThreadPoolTaskExecutor lingchatExecutor() {
        //这是spring提供的线程池。内部实现了ThreadFactory，所以他自己就是一个线程工厂
        // 创建一个Spring提供的线程池ThreadPoolTaskExecutor对象。
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        // 设置线程池在关闭时，是否等待所有任务执行完成后再关闭。
        // 打开优雅停机。spring提供的线程池内部实现了DisposableBean()方法，重写了里面的destory()的方法。
        //            里面有一个变量waitForTasksToCompleteOnShutdown默认是false，设置为true即可实现优雅停机。
        //            内部调用的还是JUC包中的 showdown()方法
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池的核心线程数。
        executor.setCorePoolSize(10);
        // 设置线程池的最大线程数。
        executor.setMaxPoolSize(10);
        // 设置线程池队列的容量。
        executor.setQueueCapacity(200);
        // 设置线程池中线程的名称前缀。
        executor.setThreadNamePrefix("lingsphere-executor-");
        //设置自定义的线程工厂，使用了 装饰器模式
        executor.setThreadFactory(new MyThreadFactory(executor));

        // 设置当线程池中的线程数量达到最大值后，新任务的处理策略。
        // 这里选择的是CallerRunsPolicy策略，即当线程池已满时，新任务会在调用execute方法的线程中运行。
        // 认为这些任务是重要的，所以选择在当前线程中执行。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        // 初始化线程池。
        executor.initialize();

        // 返回初始化后的线程池对象。
        return executor;
    }


    // 定义一个常量字符串，代表WebSocket通信线程池的名称。
    public static final String WS_EXECUTOR = "websocketExecutor";
    /**
     * 使用@Bean注解定义一个Bean，名称为LINGSPHERE_EXECUTOR。
     * @Primary注解表示当有多个同类型的Bean时，优先选择这个Bean作为注入目标。
     *
     * 专门用来 ws 之间推送消息的
     */
    @Bean(WS_EXECUTOR)
    @Primary
    public ThreadPoolTaskExecutor websocketExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //优雅停机
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池的核心线程数。
        executor.setCorePoolSize(20);
        // 设置线程池的最大线程数。
        executor.setMaxPoolSize(20);
        // 设置线程池队列的容量。
        executor.setQueueCapacity(1000);
        // 设置线程池中线程的名称前缀。
        executor.setThreadNamePrefix("websocket-executor-");
        //设置自定义的线程工厂，使用了 装饰器模式
        executor.setThreadFactory(new MyThreadFactory(executor));

        // 设置当线程池中的线程数量达到最大值后，新任务的处理策略。
        // 这里选择的是DiscardPolicy策略，即当线程池已满时，直接丢弃新任务。
        // 认为这些任务是并不重要，可有可无的，所以选择直接丢弃
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());

        // 初始化线程池。
        executor.initialize();

        // 返回初始化后的线程池对象。
        return executor;
    }
}